package com.songyuesheng.app.controller;

import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.songyuesheng.app.commom.LuckyLogs;
import com.songyuesheng.app.commom.Result;
import com.songyuesheng.app.dto.ChangePasswordDto;
import com.songyuesheng.app.dto.LoginDto;
import com.songyuesheng.app.dto.RefreshTokenDto;
import com.songyuesheng.app.dto.RegisterDto;
import com.songyuesheng.app.entity.User;
import com.songyuesheng.app.enums.LogTypeEnum;
import com.songyuesheng.app.service.UserService;
import com.songyuesheng.app.util.JwtUtil;
import com.songyuesheng.app.vo.LoginVo;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author song
 * @date 2024/3/15 15:38
 */
@RestController
public class UserController {

    @Resource
    private UserService userService;

    @GetMapping("/getUserInfo")
    public Result<?> getUserInfo() {
        return userService.getUserInfo();
    }

    /***
     * 更新头像
     * @param file
     * @return
     */
    @PostMapping("/updateAvatar")
    public Result<?> updateAvatar(@RequestParam("file") MultipartFile file) {
        return userService.updateAvatar(file);
    }

    /**
     * 用户登录
     *
     * @param loginDto 登录请求参数，包含用户名和密码
     * @return 返回登录操作的结果
     */
    @LuckyLogs(operation = "Select",type = LogTypeEnum.LOGIN)
    @PostMapping("/login")
    public Result<?> login(@RequestBody LoginDto loginDto) {
        return userService.login(loginDto);
    }

    /**
     * 用户注册
     *
     * @param registerDto 注册请求参数，包含用户名和密码
     * @return 返回登录操作的结果
     */
    @LuckyLogs(operation = "Update",type = LogTypeEnum.REGISTER)
    @PostMapping("/register")
    public Result<?> register(@RequestBody RegisterDto registerDto) {
        return userService.register(registerDto);
    }

    /**
     * 用户注册
     *
     * @param changePasswordDto 注册请求参数，包含用户名和密码
     * @return 返回登录操作的结果
     */
    @PutMapping("/changePassword")
    public Result<?> changePassword(@RequestBody ChangePasswordDto changePasswordDto) {
        return userService.changePassword(changePasswordDto);
    }
    /**
     *更新用户信息接口
     * */
    @LuckyLogs(operation = "Update",type = LogTypeEnum.UPDATE)
    @PutMapping("/updateUserInfo")
    public Result<?> updateUserInfo(@RequestBody User user) {
        return userService.updateUserInfo(user);
    }

    /**
     *查询所有用户接口
     * */
    @LuckyLogs(operation = "查询操作",type = LogTypeEnum.SELECT_ALL_USER)
    @GetMapping("/selectAll")
    public Result<?> selectAllUser() {
        return userService.selectAllUser();
    }

    /**
     *分页查询接口
     * */
    @LuckyLogs(operation = "查询操作",type = LogTypeEnum.SELECT_ALL_USER)
    @GetMapping("/selectUserByPage")
    public Result<?> selectUserByPage(@RequestParam Integer pageNum, @RequestParam Integer pageSize, @RequestParam(required = false) String username) {
        return userService.selectUserByPage(pageNum, pageSize, username);
    }

    /**
     *新增用户接口
     * */
    @LuckyLogs(operation = "Create",type = LogTypeEnum.CREATE)
    @PostMapping("/addUser")
    public Result<?> addUser(@RequestBody User user) {
        return userService.addUser(user);
    }

    /**
     *删除用户接口
     * */
    @LuckyLogs(operation = "Delete",type = LogTypeEnum.DELETE)
    @DeleteMapping("/delUser/{id}")
    public Result<?> delUser(@PathVariable Integer id) {
        return userService.delUser(id);
    }

    /**
     *批量删除用户接口
     * */
    @LuckyLogs(operation = "Delete",type = LogTypeEnum.DELETE_BATCH)
    @DeleteMapping("/del/batch")
    public Result<?> delBatchIds(@RequestBody List<Integer> ids) {
        return userService.delBatchIds(ids);
    }

    /**
     *导出用户列表接口
     * */
    @GetMapping("/export")
    public void exportData(@RequestParam(required = false) String username,
                           @RequestParam(required = false) String ids,
                           HttpServletResponse response) throws IOException {
        ExcelWriter writer = ExcelUtil.getWriter(true);
        List<User> list = new ArrayList<>();
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNotBlank(ids)) {
            //["1","2","3"]  =>  [1,2,3]
            List<Integer> idsArr = Arrays.stream(ids.split(",")).map(Integer::valueOf).collect(Collectors.toList());
            queryWrapper.in(User::getId, idsArr);
        } else {
            //全部导出或条件导出
            //模糊查询
            queryWrapper.like(StrUtil.isNotBlank(username), User::getUsername, username);
        }
        list = userService.list(queryWrapper);
        writer.write(list, true);

        // 设置浏览器响应的格式
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("用户信息表", "UTF-8") + ".xlsx");
        ServletOutputStream outputStream = response.getOutputStream();
        writer.flush(outputStream, true);
        writer.close();

        outputStream.flush();
        outputStream.close();
    }

    /**
     *批量导入用户接口
     * */
    @PostMapping("/import")
    public Result<?> importData(MultipartFile file) throws IOException {
        ExcelReader reader = ExcelUtil.getReader(file.getInputStream());
        List<User> userList = reader.readAll(User.class);

        //写入数据到数据库
        boolean b = userService.saveBatch(userList);
        return Result.success(b);
    }

    /**
     * 刷新访问令牌
     *
     * @param refreshTokenDto 刷新令牌
     * @return 新的访问令牌和刷新令牌
     */
    @PostMapping("/refreshToken")
    public Result<?> refreshToken(@RequestBody RefreshTokenDto refreshTokenDto) {
        try {
            Map<String, Object> claims = JwtUtil.resolveRefreshToken(refreshTokenDto.getRefreshToken());
            String username = (String) claims.get("sub");
            Long userId = ((Number) claims.get("userId")).longValue();

            HashMap<String, Object> map = new HashMap<>(2);
            map.put("userId", userId);

            String newAccessToken = JwtUtil.generateAccessToken(username, map);
            String newRefreshToken = JwtUtil.generateRefreshToken(username, map);

            return Result.success(new LoginVo(newAccessToken, newRefreshToken, null));
        } catch (Exception e) {
            return Result.error("刷新令牌失败: " + e.getMessage());
        }
    }
}
